package simple_sql

import (
	"database/sql"
	"errors"
	"fmt"
	"log"
	"strings"
)

// QuerySelect 结构体用于构建和执行SQL查询。
type QuerySelect struct {
	query     *sql.DB
	tx        *sql.Tx
	tableName string
	columns   []string
	where     strings.Builder
	whereArgs []any
	orderBy   []string
	limit     int
	offset    int
	err       error
}

// Where 为查询添加过滤条件。
func (q *QuerySelect) Where(opList ...Operator) *QuerySelect {
	// 如果查询条件有错误或过滤条件为空，则直接返回。
	if q.err != nil || opList == nil || len(opList) == 0 {
		return q
	}

	// 创建一个字符串构建器，用于构造过滤条件。
	var filter strings.Builder
	// 构造过滤条件并添加到where部分。
	for _, op := range opList {
		operator, value, err := op.toSql()
		if err != nil {
			q.err = err
			return q
		}
		if filter.Len() != 0 {
			filter.WriteString(" AND")
		}
		filter.WriteString(operator)
		q.whereArgs = append(q.whereArgs, value...)
	}
	// 判断是否首次的过滤条件，不是添加（AND、OR）
	q.where.WriteString(fmt.Sprintf("(%s )", filter.String()))

	// 返回Query指针，支持链式调用。
	return q
}

// And 为查询添加AND过滤条件。
func (q *QuerySelect) And(opList ...Operator) *QuerySelect {
	if q.err != nil || opList == nil || len(opList) == 0 {
		return q
	}

	q.where.WriteString(" AND")
	q.Where(opList...)

	return q
}

// Or 为查询添加OR过滤条件。
func (q *QuerySelect) Or(opList ...Operator) *QuerySelect {
	if q.err != nil || opList == nil || len(opList) == 0 {
		return q
	}

	q.where.WriteString(" OR")
	q.Where(opList...)

	return q
}

// Limit 设置查询的限制条件，即最多返回的记录数和偏移量。
func (q *QuerySelect) Limit(limit, offset int) *QuerySelect {
	if limit != 0 {
		q.limit = limit
	}
	if offset != 0 {
		q.offset = offset
	}
	return q
}

// OrderBy 设置查询结果的排序条件。
func (q *QuerySelect) OrderBy(filed ...string) *QuerySelect {
	for _, column := range filed {
		if strings.HasPrefix(column, "-") {
			q.orderBy = append(q.orderBy, fmt.Sprintf(" %s DESC", column[1:]))
		} else {
			q.orderBy = append(q.orderBy, fmt.Sprintf(" %s ASC", column))
		}
	}

	return q
}

// String 返回构建的SQL查询字符串。
func (q *QuerySelect) String() string {
	var query strings.Builder

	// 拼接查询字段
	if q.columns == nil {
		query.WriteString("SELECT * FROM")
	} else {
		query.WriteString(fmt.Sprintf("SELECT %s FROM", strings.Join(q.columns, ",")))
	}

	// 拼接表名
	query.WriteString(" " + q.tableName)

	// 拼接查询条件
	if q.where.Len() != 0 {
		query.WriteString(fmt.Sprintf(" WHERE %s", q.where.String()))
	}

	// 拼接排序条件
	if len(q.orderBy) != 0 {
		query.WriteString(fmt.Sprintf(" ORDER BY%s", strings.Join(q.orderBy, ",")))
	}

	// 拼接限制条件
	if q.limit != 0 {
		query.WriteString(fmt.Sprintf(" LIMIT %d", q.limit))
		if q.offset != 0 {
			query.WriteString(fmt.Sprintf(" OFFSET %d", q.offset))
		}
	}

	// Return the constructed SQL query string.
	return query.String()
}

// First 执行查询并返回第一条记录。
func (q *QuerySelect) First() (map[string]any, error) {
	q.Limit(1, 0)
	var rows *sql.Rows
	var err error
	if q.tx != nil {
		rows, err = q.tx.Query(q.String(), q.whereArgs...)
	} else {
		rows, err = q.query.Query(q.String(), q.whereArgs...)
	}
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var resp []map[string]any

	err = q.processRows(rows, &resp)
	if err != nil {
		return nil, err
	}

	return resp[0], nil
}

// All 执行查询并返回所有记录。
func (q *QuerySelect) All() ([]map[string]any, error) {
	var rows *sql.Rows
	var err error
	if q.tx != nil {
		rows, err = q.tx.Query(q.String(), q.whereArgs...)
	} else {
		rows, err = q.query.Query(q.String(), q.whereArgs...)
	}
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var resp []map[string]any

	err = q.processRows(rows, &resp)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

// processRows 辅助函数：处理 rows.Next() 和结果转换
func (q *QuerySelect) processRows(rows *sql.Rows, resp *[]map[string]any) error {

	// 返回字段名称
	columns, err := rows.Columns()
	if err != nil {
		return err
	}

	scanArgs := make([]interface{}, len(columns))
	for i := range scanArgs {
		scanArgs[i] = new(interface{})
	}

	for rows.Next() {
		if err := rows.Scan(scanArgs...); err != nil {
			return err
		}

		result := make(map[string]any)
		for i, column := range columns {
			v := *(scanArgs[i].(*interface{}))
			switch v.(type) {
			case []uint8:
				result[column] = string(v.([]uint8))
			default:
				result[column] = v
			}
		}

		*resp = append(*resp, result)
	}

	// 检查 rows.Next() 中可能的错误
	if err = rows.Err(); err != nil {
		return err
	}

	return nil
}

func (q *QuerySelect) Exist() bool {
	// 构造 SQL 查询语句，避免直接拼接字符串
	query := "SELECT 1 FROM " + q.tableName + " WHERE " + q.where.String() + " LIMIT 1"

	// 提前计算 whereArgs，减少重复调用
	args := q.whereArgs

	// 执行查询
	var exist int
	var err error
	if q.tx != nil {
		err = q.tx.QueryRow(query, args...).Scan(&exist)
	} else {
		err = q.query.QueryRow(query, args...).Scan(&exist)
	}

	// 错误处理
	if err == nil {
		return true // 存在记录
	} else if errors.Is(err, sql.ErrNoRows) {
		return false // 无记录
	}

	// 记录其他错误以便调试
	log.Printf("Error during Exist check: %v", err)
	return false
}
